#include "DatabaseAccess.h"
#include <fstream>
#include "common.h"

using namespace std;

CDatabaseAccess::CDatabaseAccess(void)
{
}

CDatabaseAccess::~CDatabaseAccess(void)
{
}

bool CDatabaseAccess::ReadFileCard(CCard& g_Card, const char *cFileName)
{
    char cLine[200];
    char *cTmp1, *cTmp2, *cTmp3;

    ifstream fRead(cFileName);
    if (fRead == NULL)
        return false;
    while (true)
    {
        if (fRead.eof())
            break;
        fRead.getline(cLine, 200);
        if (strlen(cLine) > 0)
        {
            cTmp1 = strtok(cLine, DELIM);
            if (strcmp(cTmp1,g_Card.GetCardID()) == 0)
            { 
                cTmp1 = strtok(NULL, DELIM);
                g_Card.SetAccountID(cTmp1);
                cTmp1 = strtok(NULL, DELIM);
                g_Card.SetPin(cTmp1);
                cTmp1 = strtok(NULL, DELIM_DATE);
                cTmp2 = strtok(NULL, DELIM_DATE);
                cTmp3 = strtok(NULL, DELIM);
                CDate dDateCreate(atoi(cTmp1), atoi(cTmp2), atoi(cTmp3));
                g_Card.SetDateCreate(dDateCreate);

                cTmp1 = strtok(NULL, DELIM_DATE);
                cTmp2 = strtok(NULL, DELIM_DATE);
                cTmp3 = strtok(NULL, DELIM);
                CDate dDateActive(atoi(cTmp1), atoi(cTmp2), atoi(cTmp3));
                g_Card.SetDateActive(dDateActive);

                cTmp1 = strtok(NULL, DELIM_DATE);
                cTmp2 = strtok(NULL, DELIM_DATE);
                cTmp3 = strtok(NULL, DELIM);
                CDate dDateLock(atoi(cTmp1), atoi(cTmp2), atoi(cTmp3));
                g_Card.SetDateLock(dDateLock);

                cTmp1 = strtok(NULL, DELIM);
                g_Card.SetCardStatus(atoi(cTmp1));   
                fRead.close();
                return true;
            }
        }
    }
    fRead.close();
    return false;
}

bool CDatabaseAccess::ReadFileAccount(CAccount& objAcc, const char *cFileName)
{
    char cLine[200];
    char *cTmp;

    ifstream fRead(cFileName);
    if (fRead == NULL)
        return false;
    while (true)
    {
        if (fRead.eof())
            break;
        fRead.getline(cLine, 200);
        if (strlen(cLine) > 0)
        {
            cTmp = strtok(cLine, DELIM);
            if (strcmp(cTmp,objAcc.GetAccountID()) == 0)
            { 
                cTmp = strtok(NULL, DELIM);
                objAcc.SetFullName(cTmp);
                cTmp = strtok(NULL, DELIM);
                objAcc.SetPhone(cTmp);
                cTmp = strtok(NULL, DELIM);
                objAcc.SetAddress(cTmp);
                cTmp = strtok(NULL, DELIM);
                objAcc.SetAccountStatus(atoi(cTmp));
                cTmp = strtok(NULL, DELIM);
                objAcc.SetSex(cTmp);
                cTmp = strtok(NULL, DELIM);
                objAcc.SetType(cTmp);
                cTmp = strtok(NULL, DELIM);
                objAcc.SetBalance(atoi(cTmp));
                fRead.close();
                return true;
            }
        }
    }
    fRead.close();
    return false;
}

int CDatabaseAccess::ReadFileTransaction(CTransaction &objTransaction, const char *cFileName)
{
    g_iTransID = 1;
	char cLine[200];
	char *cTmp1, *cTmp2, *cTmp3;
	int iCounter = 0;

	ifstream fRead(cFileName);
	if (fRead == NULL)
		return 0;

	while (true)
	{
		if (fRead.eof())
			break;
		fRead.getline(cLine, 200);
		if (strlen(cLine) > 0)
		{
			cTmp1 = strtok(cLine, DELIM);
			cTmp2 = strtok(NULL, DELIM);
			if (strcmp(cTmp2, objTransaction.GetAccountID()) == 0)
			{ 
				cTmp2 = strtok(NULL, DELIM);
				cTmp1 = strtok(NULL, DELIM_DATE);  // day 
				cTmp2 = strtok(NULL, DELIM_DATE);  // month
				cTmp3 = strtok(NULL, DELIM); // year 

				if ( atoi(cTmp1) == objTransaction.GetDay() 
					&& atoi(cTmp2) == objTransaction.GetMonth()
					&& atoi(cTmp3) == objTransaction.GetYear() ) 
				{
					iCounter ++;
				}
			}
            ++g_iTransID; 
		}
       
	}
    fRead.close();
	return iCounter;
}

bool CDatabaseAccess::WriteFileCard(CCard& g_Card, const char *cFileName)
{
    char cLine[200];
    char cLineTmp[200];
    char *cTmp;

    ifstream fRead(cFileName);
    ofstream fWrite(FILE_CARD_TMP);
    if (fRead == NULL)
        return false;
    while (true)
    {
        if (fRead.eof())
            break;
        fRead.getline(cLine, 200);
        
        if (strlen(cLine) > 0)
        {
            strcpy_s(cLineTmp, cLine);
            cTmp = strtok(cLineTmp, DELIM);
            if (strcmp(cTmp, g_Card.GetCardID()) != 0)
                fWrite << cLine << endl;
            else
            {
                fWrite << g_Card.GetCardID() << DELIM 
                    << g_Card.GetAccountID() << DELIM
                    << g_Card.GetPin() << DELIM
                    << g_Card.GetDateCreate().GetDay() << DELIM_DATE
                    << g_Card.GetDateCreate().GetMonth() << DELIM_DATE
                    << g_Card.GetDateCreate().GetYear() << DELIM
                    << g_Card.GetDateActive().GetDay() << DELIM_DATE
                    << g_Card.GetDateActive().GetMonth() << DELIM_DATE
                    << g_Card.GetDateActive().GetYear() << DELIM
                    << g_Card.GetDateLock().GetDay() << DELIM_DATE
                    << g_Card.GetDateLock().GetMonth() << DELIM_DATE
                    << g_Card.GetDateLock().GetYear() << DELIM
                    << g_Card.GetCardStatus() << endl;
            }
        }
    }
    fRead.close();
    fWrite.close();
    remove(cFileName);
    rename(FILE_CARD_TMP, cFileName);
    return true;
}

bool CDatabaseAccess::WriteFileTransaction(CTransaction& objTrans, const char *cFileName)
{
    ofstream fWrite(cFileName, ios::app);
    if (fWrite == NULL)
        return false;
    fWrite << objTrans.GetTransactionID() << DELIM 
        << objTrans.GetAccountID() << DELIM
        << objTrans.GetFullName() << DELIM
        << objTrans.GetDay() << DELIM_DATE
        << objTrans.GetMonth() << DELIM_DATE
        << objTrans.GetYear() << DELIM
        << objTrans.GetValueTrans() << endl;
    fWrite.close();
    return true;
}

bool CDatabaseAccess::WriteFileAccount(CAccount& objAcc, const char *cFileName, const char *cNewFile) 
{
    ofstream ofFile;
    ifstream ifFile;
    char sBuffer[256];
    char *sTmp, sLine[256];

    ifFile.open(cFileName);
    ofFile.open(cNewFile);

    if (!ifFile || !ofFile)
        return false;

    while (!ifFile.eof()) 
    {
        ifFile.getline(sBuffer, 256);
        if (strlen(sBuffer) > 0) 
        {
            strcpy_s(sLine, sBuffer);
            sTmp = strtok(sBuffer, DELIM);  // AccountID
            if (strcmp(sTmp, objAcc.GetAccountID()) == 0 ) 
            {
                // rewrite into new line
                ofFile << objAcc.GetAccountID() << DELIM << objAcc.GetFullName() << DELIM 
                    << objAcc.GetPhone() << DELIM << objAcc.GetAddress() << DELIM 
                    << objAcc.GetAccountStatus() << DELIM << objAcc.GetSex() << DELIM 
                    << objAcc.GetType() << DELIM << objAcc.GetBalance() << endl;
            } 
            else 
            {
                ofFile << sLine << endl;
            }
        }
    }  

    ifFile.close();
    // delete a old file
    if (remove(cFileName) != 0) {
        return false;
    }
    // rename a new file
    ofFile.close();
    if (rename(cNewFile, cFileName) != 0) {
        return false;
    }

    return true;
} 

long CDatabaseAccess::ReadFileATM(const char *cFileName)
{
    char cLine[20];
    long lMoneyATM;

    ifstream fRead(cFileName);
    if (fRead == NULL)
        return -1;
    while (true)
    {
        if (fRead.eof())
            break;
        fRead.getline(cLine, 20);
        if (strlen(cLine) > 0)
        {
            lMoneyATM = atoi(cLine);
            fRead.close();
            return lMoneyATM;          
        }
    }
}

void CDatabaseAccess::WriteFileATM(const char *cFileName, long lATMMoney)
{
    ofstream fWrite(cFileName);
    fWrite << lATMMoney;
    fWrite.close();
}